<?php
$st = microtime(true);
header('Content-Type: text/html; charset=utf-8');

// Get class and method name.
$class = ucwords((empty($_GET['c'])) ? 'example' : $_GET['c']);
$method = (empty($_GET['m'])) ? 'index' : $_GET['m'];

$file = App::ctl_dir . '/' . $class . App::ctl_aff;// Controller class file path.

App::debug('Request: dispatch to ' . $method . '@' . $file);

// Init the framework(when first run).
App::init();

// Load controller class file.
if (file_exists($file)){
    require $file;
} else if(App::$debug) {
    
    // Create the module.
    App::create_module($class);
    require $file;
} else {

    App::info('App error: Controller(' . $class . '@' . $file . ') not found!');
    die;
}

App::debug('Load controller: ' . $class . '@' . $file);

if (method_exists($class, $method)) {

    $instance = new $class();
	$instance->$method();	
	App::debug('Invoked method: ' . $method . '@' . $file);	

    if(file_exists(App::tpl_dir . '/' . $class . '/' . $method . App::tpl_aff)) {
        $sy = App::init_smarty();

        foreach (get_class_vars(get_class($instance)) as $name=>$value) {
            $sy->assign($name, $instance->$name);
        }		
        $sy->display($class . '/' . $method . App::tpl_aff);
        App::debug('Complete(' . 1000*round((microtime(true)-$st), 5) . 'ms, base on ' . App::product . ' v' . App::version .')');
    }
} else {
    App::info('Method(' . $method . '@' . $file .') not found!');
    App::debug('Complete(' . 1000*round((microtime(true)-$st), 5) . 'ms, base on ' . App::product . ' v' . App::version .')');
}


class App {

    const product = 'xiaophp';
    const version = '0.1.2';
    
    // Conf for the frameword.
    const ctl_dir = 'ctl';
    const ctl_aff = '.php';

    // Conf for smarty.
    const smarty_dir = '../smarty/libs/Smarty.class.php';
    const tpl_dir = 'tpl';
    const tpl_aff = '.html';
    const left_delimiter = '<{';
    const right_delimiter = '}>';
    const tmp_dir = 'tmp';
    const compiled_dir = 'tmp/compiled';
    static $cache_dir = 'tmp/cache';
    static $caching = false;
    static $cache_lifetime = 60;

    static $debug = true;

    /**
     * Init the framework.
     */
    static function init() {

        // Init the framework directory structure.
        if(!is_dir(self::tmp_dir)) {
			if(!file_exists(self::smarty_dir)){
				App::info('App error: Failed to find \'' . self::smarty_dir . '\'');
				die;
			}
	
            mkdir(self::tmp_dir);
            mkdir(self::compiled_dir);
            mkdir(self::ctl_dir);
            mkdir(self::tpl_dir);
            mkdir(self::$cache_dir);

            // Create example module.
            self::create_module('Example');

            App::debug('Init the framework(' . self::product . ' v' . self::version .') complete');

        }
    }

    /**
     * Init Smarty.
     */
    static function init_smarty() {
        
        include_once(self::smarty_dir);
        $smarty = new Smarty();
        $smarty->template_dir = self::tpl_dir;
        $smarty->compile_dir = self::compiled_dir;
        $smarty->left_delimiter = self::left_delimiter;
        $smarty->right_delimiter = self::right_delimiter;

        $smarty->cache_dir = self::$cache_dir;
        $smarty->cache_lifetime = self::$cache_lifetime;
        $smarty->caching = self::$caching;

        App::debug('Init Smarty complete');

        return $smarty;
    }
    
    /**
     * DEBUG.
     */
    static function debug($info) {
        if(self::$debug){
            echo '<span style="font-size:12px;background-color:#e8e8ff;width:100%;"><font color="blue">' . date('H:i:s') . ' DEBUG>></font>' . $info .'</span><br />';
        }
    }
    
    /**
     * INFO.
     */
    static function info($info) {
        echo '<span style="font-size:12px;background-color:#ddd;width:100%;"><font color="blue">' . date('H:i:s') . ' INFO>></font>' . $info .'</span><br />';
    }
    
    /**
     * Create a file.
     */
    static function create_file($path, $content) {
        $fp = fopen($path, 'w+');
        fputs($fp, $content);
        fclose($fp);
    }

    /**
     * Create module.
     */
    static function create_module($name) {

        // Create controller.
        self::create_file(self::ctl_dir . '/' . ucwords($name) . self::ctl_aff, "<?php\r\n\r\nclass " . ucwords($name) . " {\r\n\r\n    var " . '$msg;' . "\r\n\r\n    function index() {\r\n        ".'$this->msg'." = 'Default message from index@$name module<br />恭喜发财 新春愉快！It work! ' . date('Y-m-d H:i:s') . '<br />Base on ' . App::product . ' v' . App::version . '.';\r\n    }\r\n\r\n    function php() {\r\n        echo 'Default message from php@$name module<br />恭喜发财 新春愉快！It work! ' . date('Y-m-d H:i:s') . '<br />Base on ' . App::product . ' v' . App::version . '.';\r\n    }" . "\r\n}");
        App::debug('Create ' . $name . ' controller(' . self::ctl_dir . '/' . ucwords($name) . self::ctl_aff .')');

        // Create template.         
        mkdir(self::tpl_dir . '/' . strtolower($name));
        self::create_file(self::tpl_dir . '/' . strtolower($name) . '/index' . self::tpl_aff, '<{$msg}><br />');
        App::debug('Create ' . $name . ' template(' . self::tpl_dir . '/' . strtolower($name) . '/index' . self::tpl_aff .')');
    }

}